﻿#ifndef COLLISION_H
#define COLLISION_H
#include <cmath>
#include <algorithm>

// Collision box types
enum class CollisionBoxType {
	Point,
	Rectangle,
	Circle
};

// Forward declarations
class PointCollisionBox;
class RectangleCollisionBox;
class CircleCollisionBox;


// Abstract collision box base class
class CollisionBox {
public:
	CollisionBox();
	CollisionBox(CollisionBoxType type);
	virtual ~CollisionBox() = default;

	// Get collision box type
	CollisionBoxType getType() const;

	// Pure virtual function: check collision with other collision box
	virtual bool checkCollision(const CollisionBox& other) const = 0;

	// Virtual functions: collision detection with specific collision box types
	virtual bool checkCollisionWithPoint(const PointCollisionBox& point) const = 0;
	virtual bool checkCollisionWithRectangle(const RectangleCollisionBox& rect) const = 0;
	virtual bool checkCollisionWithCircle(const CircleCollisionBox& circle) const = 0;

	// Static method: detect collision between any two collision boxes
	static bool checkCollision(const CollisionBox& box1, const CollisionBox& box2);

private:
	CollisionBoxType type_; // Collision box type
};

// Point collision box
class PointCollisionBox : public CollisionBox {
public:
	PointCollisionBox();
	PointCollisionBox(float x, float y);

	float getX() const;
	float getY() const;

	bool setX(float x);
	bool setY(float y);

	// Check collision with other collision boxes
	bool checkCollision(const CollisionBox& other) const override;

	bool checkCollisionWithPoint(const PointCollisionBox& point) const override;
	bool checkCollisionWithRectangle(const RectangleCollisionBox& rect) const override;
	bool checkCollisionWithCircle(const CircleCollisionBox& circle) const override;

private:
	float x_, y_; // Point coordinates
};

// Rectangle collision box
class RectangleCollisionBox : public CollisionBox {
public:
	RectangleCollisionBox();
	RectangleCollisionBox(float x, float y, float width, float height);

	float getX() const;
	float getY() const;
	float getWidth() const;
	float getLength() const;

	bool setX(float x);
	bool setY(float y);
	bool setWidth(float width);
	bool setLength(float length);

	// Check collision with other collision boxes
	bool checkCollision(const CollisionBox& other) const override;

	bool checkCollisionWithPoint(const PointCollisionBox& point) const override;
	bool checkCollisionWithRectangle(const RectangleCollisionBox& rect) const override;
	bool checkCollisionWithCircle(const CircleCollisionBox& circle) const override;

private:
	float x_, y_;       // Rectangle top-left coordinates
	float width_, length_;
};

// Circle collision box
class CircleCollisionBox : public CollisionBox {
public:

	CircleCollisionBox();
	CircleCollisionBox(float x, float y, float radius);

	float getX() const;
	float getY() const;
	float getRadius() const;

	bool setX(float x);
	bool setY(float y);
	bool setRadius(float radius);

	// Check collision with other collision boxes
	bool checkCollision(const CollisionBox& other) const override;

	bool checkCollisionWithPoint(const PointCollisionBox& point) const override;
	bool checkCollisionWithRectangle(const RectangleCollisionBox& rect) const override;
	bool checkCollisionWithCircle(const CircleCollisionBox& circle) const override;

private:
	float x_, y_;  // Circle center coordinates
	float radius_; // Circle radius
};


#endif

